package com.k2data.app.k2bq.siem.run;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.k2data.app.k2bq.siem.common.GlobalVariables;
import com.k2data.app.k2bq.siem.utils.HttpsUtils;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import com.k2data.app.k2bq.siem.request.RequestConf;
import com.k2data.app.k2bq.siem.request.RequestConfUtil;
import com.k2data.app.k2bq.siem.utils.DatabaseUtils;
import com.k2data.app.k2bq.siem.utils.OkHttpUtils;
import com.k2data.app.k2bq.siem.utils.exception.SiemException;

import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

public class Siem {

    public static void main(String[] args) {
        try {
            //Http Client
            OkHttpClient client = new OkHttpClient().newBuilder().sslSocketFactory(HttpsUtils.createSSLSocketFactory(), new HttpsUtils.TrustAllManager()).hostnameVerifier(new HttpsUtils.TrustAllHostnameVerifier()).build();
            //Login
            login(client, RequestConfUtil.getLoginRequest());

            DatabaseUtils databaseUtils = new DatabaseUtils();
            Date time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2018-12-01 00:00:00");
            while (time.before(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2018-12-12 23:59:59"))) {
                System.out.println("开始读取： " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time));
                try {
                    doLogSource(time, databaseUtils, client);
                    doRequest(time, databaseUtils, client, GlobalVariables.REQUEST_QUERYID_32);
                    doRequest(time, databaseUtils, client, GlobalVariables.REQUEST_QUERYID_34);
                    doRequest(time, databaseUtils, client, GlobalVariables.REQUEST_QUERYID_35);
                    doRequest(time, databaseUtils, client, GlobalVariables.REQUEST_QUERYID_37);
                    doRequest(time, databaseUtils, client, GlobalVariables.REQUEST_QUERYID_39);
                } catch (SiemException e) {
                    System.out.println("读取失败： " + e.getMessage());
                    doUpdate(String.format("insert into bq_siem.log_error (t_name, time) values ('%s', '%s')", GlobalVariables.SIEM_MINUTE, e.getMessage()));
                }
                time = getEndTime(time);
                TimeUnit.SECONDS.sleep(1);
            }
            databaseUtils.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    private static void doLogSource(Date time, DatabaseUtils databaseUtils, OkHttpClient client) throws SiemException {
        try {
            //Query Job
            RequestConf rc = RequestConfUtil.getRunningQueryRequest(getSiemStartTime(time), getSiemEndTime(time), GlobalVariables.REQUEST_QUERYID_113);
            Response response = OkHttpUtils.send(client, rc);
            //Query Status
            rc = RequestConfUtil.getResultRequest(JSON.parseObject(response.body().string()).getString("location"));
            //Query Results
            if (queryComplete(client, rc)) {
                response = OkHttpUtils.send(client, RequestConfUtil.getResultRequest(JSON.parseObject(OkHttpUtils.send(client, rc).body().string()).getString("location")));
                String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                String year = new SimpleDateFormat("yyyy").format(getEndTime(time));
                String month = new SimpleDateFormat("MM").format(getEndTime(time));
                String day = new SimpleDateFormat("dd").format(getEndTime(time));
                String hour = new SimpleDateFormat("HH").format(getEndTime(time));
                String min = new SimpleDateFormat("mm").format(getEndTime(time));
                String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
                String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(getEndTime(time));
                JSONArray data = JSON.parseObject(response.body().string()).getJSONArray("data");
                for (Object object : data) {
                    JSONArray item = JSON.parseArray(object.toString());
                    String logSource = item.get(1).toString();
                    String logCount = item.get(2).toString();
                    String logSum = item.get(3).toString();
                    databaseUtils.doUpdate(String.format("insert into bq_siem.base_logsource_top (create_time, t_year, t_month, t_day, t_hour, t_min, log_source, log_count, log_sum, start_time, end_time) values ('%s', %s, %s, %s, %s, %s, '%s', %s, %s, '%s', '%s')", createTime, year, month, day, hour, min, logSource, logCount, logSum, startTime, endTime));
                }
            }
        } catch (SQLException e) {
            System.out.println(e.getMessage());
            databaseUtils.doSQLException(e);
            //rollback
            String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
            doUpdate(String.format("delete from bq_siem.base_logsource_top where start_time = '%s'", startTime));
            throw new SiemException(startTime);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
            throw new SiemException(startTime);
        }
    }

    private static void doRequest(Date time, DatabaseUtils databaseUtils, OkHttpClient client, String request) throws SiemException {
        try {
            //Query Job
            RequestConf rc = RequestConfUtil.getRunningQueryRequest(getSiemStartTime(time), getSiemEndTime(time), request);
            Response response = OkHttpUtils.send(client, rc);
            //Query Status
            rc = RequestConfUtil.getResultRequest(JSON.parseObject(response.body().string()).getString("location"));
            //Query Results
            if (queryComplete(client, rc)) {
                response = OkHttpUtils.send(client, RequestConfUtil.getResultRequest(JSON.parseObject(OkHttpUtils.send(client, rc).body().string()).getString("location")));
                String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                String year = new SimpleDateFormat("yyyy").format(getEndTime(time));
                String month = new SimpleDateFormat("MM").format(getEndTime(time));
                String day = new SimpleDateFormat("dd").format(getEndTime(time));
                String hour = new SimpleDateFormat("HH").format(getEndTime(time));
                String min = new SimpleDateFormat("mm").format(getEndTime(time));
                String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
                String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(getEndTime(time));
                JSONArray data = JSON.parseObject(response.body().string()).getJSONArray("data");
                for (Object object : data) {
                    JSONArray item = JSON.parseArray(object.toString());
                    String name = item.get(0).toString();
                    String count = item.get(1).toString();
                    String sum = item.get(2).toString();
                    databaseUtils.doUpdate(String.format("insert into bq_siem.base_net_top (create_time, t_year, t_month, t_day, t_hour, t_min, log_source, log_count, log_sum, start_time, end_time) values ('%s', %s, %s, %s, %s, %s, '%s', %s, %s, '%s', '%s')", createTime, year, month, day, hour, min, name, count, sum, startTime, endTime));
                }
            }
        } catch (SQLException e) {
            System.out.println(e.getMessage());
            databaseUtils.doSQLException(e);
            //rollback
            String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
            doUpdate(String.format("delete from bq_siem.base_net_top where start_time = '%s'", startTime));
            throw new SiemException(startTime);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
            throw new SiemException(startTime);
        }
    }

    private static void doUpdate(String sql) {
        try {
            DatabaseUtils databaseUtils = new DatabaseUtils();
            databaseUtils.doUpdate(sql);
            databaseUtils.close();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }

    private static void login(OkHttpClient client, RequestConf rc) throws SiemException {
        try {
            Response response = Optional.ofNullable(OkHttpUtils.send(client, rc)).orElseThrow(IOException::new);
            GlobalVariables.AUTH_HEADER.put("Cookie", response.header("Set-Cookie"));
            GlobalVariables.AUTH_HEADER.put("X-Xsrf-Token", response.header("Xsrf-Token"));
            response.close();
        } catch (Exception e) {
            throw new SiemException("login error");
        }
    }

    private static boolean queryComplete(OkHttpClient client, RequestConf rc) throws SiemException {
        try {
            //查询任务进度100%
            if (JSON.parseObject(OkHttpUtils.send(client, rc).body().string()).getInteger("progress") == 100) {
                return true;
            } else {
                TimeUnit.SECONDS.sleep(1);
                return queryComplete(client, rc);
            }
        } catch (Exception e) {
            throw new SiemException("queryComplete error");
        }
    }

    private static String getSiemStartTime(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.add(Calendar.HOUR, -8);
        return new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(calendar.getTime());
    }

    private static String getSiemEndTime(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.add(Calendar.HOUR, -8);
        calendar.add(Calendar.MINUTE, GlobalVariables.SIEM_MINUTE);
        return new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(calendar.getTime());
    }

    private static Date getEndTime(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.add(Calendar.MINUTE, GlobalVariables.SIEM_MINUTE);
        return calendar.getTime();
    }

}